#pragma once

namespace DirectUI
{
	template <
		typename baseClass, 
		typename className, 
		typename valType, 
		typename interfacename>
	class CUIValueObjectBase0
		: public CUINoAggregateObjectImplHelper<baseClass, className, interfacename>
	{
	public:
		virtual	valType	GetValue() { return m_Value; }
		virtual	void	SetValue(valType value) { m_Value = value; }
	protected:
		valType			m_Value;
	};

	template <
		typename baseClass, 
		typename className, 
		typename valType, 
		typename interfacename>
	class CUIValueObjectBase
		: public CUIValueObjectBase0<baseClass, className, valType, interfacename>
	{
	public:
		virtual	bool	IsLess(IUIObject* lpObject) 
		{ 
			className* p = GetPtr(lpObject);
			if ( !p ) return false;
			return m_Value < p->m_Value;
		}
		virtual bool	IsEqual(IUIObject* lpObject) 
		{
			className* p = GetPtr(lpObject);
			if ( !p ) return false;
			return m_Value == p->m_Value;
		}
		virtual	void	Copy(IUIObject* lpObject) 
		{
			className* p = GetPtr(lpObject);
			if ( p ) m_Value = p->m_Value;
		}
	};

	class CUIObjectHelper
	{
	public:
		static RECT UIRectToRect(UIRect rc)
		{
			RECT rcRet = {(__int32)rc.left, (__int32)rc.top, (__int32)rc.right, (__int32)rc.bottom};
			return rcRet;
		}
		static UIRect RectToUIRect(RECT rc)
		{
			UIRect rcRet = {(double)rc.left, (double)rc.top, (double)rc.right, (double)rc.bottom};
			return rcRet;
		}
	public:
		CUIObjectHelper(IUIObject* lpObj) : m_spObject(lpObj) { }
	
		bool	GetVal(bool DefaultVal = false) 
		{
			CUIObjectQIPtr<IUIBool> sp(m_spObject);
			if ( sp )
				return sp->GetValue();
			return DefaultVal;
		}
		bool	SetVal(bool Val)
		{
			CUIObjectQIPtr<IUIBool> sp(m_spObject);
			if ( sp )
			{
				sp->SetValue(Val);
				return true;
			}
			return false;
		}

		__int32	GetVal(__int32 DefaultVal = 0) 
		{
			CUIObjectQIPtr<IUIInt32> sp(m_spObject);
			if ( sp )
				return sp->GetValue();
			return DefaultVal;
		}
		bool	SetVal(__int32 Val)
		{
			CUIObjectQIPtr<IUIInt32> sp(m_spObject);
			if ( sp )
			{
				sp->SetValue(Val);
				return true;
			}
			return false;
		}

		__int64	GetVal(__int64 DefaultVal = 0) 
		{
			CUIObjectQIPtr<IUIInt64> sp(m_spObject);
			if ( sp )
				return sp->GetValue();
			return DefaultVal;
		}
		bool	SetVal(__int64 Val)
		{
			CUIObjectQIPtr<IUIInt64> sp(m_spObject);
			if ( sp )
			{
				sp->SetValue(Val);
				return true;
			}
			return false;
		}

		float	GetVal(float DefaultVal = 0) 
		{
			CUIObjectQIPtr<IUIFloat> sp(m_spObject);
			if ( sp )
				return sp->GetValue();
			return DefaultVal;
		}
		bool	SetVal(float Val)
		{
			CUIObjectQIPtr<IUIFloat> sp(m_spObject);
			if ( sp )
			{
				sp->SetValue(Val);
				return true;
			}
			return false;
		}

		double	GetVal(double DefaultVal) 
		{
			CUIObjectQIPtr<IUIDouble> sp(m_spObject);
			if ( sp )
				return sp->GetValue();
			return DefaultVal;
		}
		bool	SetVal(double Val)
		{
			CUIObjectQIPtr<IUIDouble> sp(m_spObject);
			if ( sp )
			{
				sp->SetValue(Val);
				return true;
			}
			return false;
		}

		wchar_t*	GetVal(wchar_t* DefaultVal = NULL) 
		{
			CUIObjectQIPtr<IUIString> sp(m_spObject);
			if ( sp )
				return sp->GetValue();
			return DefaultVal;
		}
		bool	SetVal(wchar_t* Val)
		{
			CUIObjectQIPtr<IUIString> sp(m_spObject);
			if ( sp )
			{
				sp->SetValue(Val);
				return true;
			}
			return false;
		}

		UIPoint	GetVal(double x, double y) 
		{
			CUIObjectQIPtr<IUIPoint> sp(m_spObject);
			if ( sp )
				return sp->GetValue();
			UIPoint point = {x, y};
			return point;
		}
		bool	SetVal(UIPoint Val)
		{
			CUIObjectQIPtr<IUIPoint> sp(m_spObject);
			if ( sp )
			{
				sp->SetValue(Val);
				return true;
			}
			return false;
		}

		UIRect	GetVal(double x, double y, double cx, double cy) 
		{
			CUIObjectQIPtr<IUIRect> sp(m_spObject);
			if ( sp )
				return sp->GetValue();
			UIRect point = {x, y, cx, cy};
			return point;
		}
		bool	SetVal(UIRect Val)
		{
			CUIObjectQIPtr<IUIRect> sp(m_spObject);
			if ( sp )
			{
				sp->SetValue(Val);
				return true;
			}
			return false;
		}
	private:
		CUIObjectPtr<IUIObject>	m_spObject;
	};

	class CUIBoolObject 
		: public CUIValueObjectBase<IUIBool, CUIBoolObject, bool, IUIBool>
	{
		DECLARE_CLASS(CUIBoolObject, bool)
	public:
		CUIBoolObject() { m_Value = 0; }
		CUIBoolObject(bool value) { m_Value = value; }
	};

	class CUIInt32Object 
		: public CUIValueObjectBase<IUIInt32, CUIInt32Object, __int32, IUIInt32>
	{
		DECLARE_CLASS(CUIInt32Object, int32)
	public:
		CUIInt32Object() { m_Value = 0; }
		CUIInt32Object(__int32 value) { m_Value = value; }
	};
	class CUIInt64Object 
		: public CUIValueObjectBase<IUIInt64, CUIInt64Object, __int64, IUIInt64>
	{
		DECLARE_CLASS(CUIInt64Object, int64)
	public:
		CUIInt64Object() { m_Value = 0; }
		CUIInt64Object(__int32 value) { m_Value = value; }
	};
	class CUIFloatObject 
		: public CUIValueObjectBase<IUIFloat, CUIFloatObject, float, IUIFloat>
	{
		DECLARE_CLASS(CUIFloatObject, float)
	public:
		CUIFloatObject() { m_Value = 0; }
		CUIFloatObject(float value) { m_Value = value; }
	};
	class CUIDoubleObject 
		: public CUIValueObjectBase<IUIDouble, CUIDoubleObject, double, IUIDouble>
	{
		DECLARE_CLASS(CUIDoubleObject, double)
	public:
		CUIDoubleObject() { m_Value = 0; }
		CUIDoubleObject(double value) { m_Value = value; }
	};
	class CUIPointObject
		: public CUIValueObjectBase0<IUIPoint, CUIPointObject, UIPoint, IUIPoint>
	{
		DECLARE_CLASS(CUIPointObject, point)
	public:
		CUIPointObject() { m_Value.x = m_Value.y = 0.0; }
		CUIPointObject(UIPoint value) { m_Value = value; }
		virtual	bool	IsLess(IUIObject* lpObject) 
		{ 
			CUIPointObject* p = GetPtr(lpObject);
			if ( !p ) return false;
			return m_Value.x < p->m_Value.x && m_Value.y <  p->m_Value.y;
		}
		virtual bool	IsEqual(IUIObject* lpObject) 
		{
			CUIPointObject* p = GetPtr(lpObject);
			if ( !p ) return false;
			return m_Value.x == p->m_Value.x && m_Value.y ==  p->m_Value.y;
		}
		virtual	void	Copy(IUIObject* lpObject) 
		{
			CUIPointObject* p = GetPtr(lpObject);
			if ( p ) m_Value = p->m_Value;
		}
	};
	class CUIRectObject
		: public CUIValueObjectBase0<IUIRect, CUIRectObject, UIRect, IUIRect>
	{
		DECLARE_CLASS(CUIRectObject, rect)
	public:
		CUIRectObject() { m_Value.left = m_Value.top = m_Value.right = m_Value.bottom = 0.0; }
		CUIRectObject(UIRect value) { m_Value = value; }
		virtual	bool	IsLess(IUIObject* lpObject) 
		{ 
			CUIRectObject* p = GetPtr(lpObject);
			if ( !p ) return false;
			return m_Value.left > p->m_Value.left
				&& m_Value.top > p->m_Value.top
				&& m_Value.right < p->m_Value.right
				&& m_Value.bottom < p->m_Value.bottom;
		}
		virtual bool	IsEqual(IUIObject* lpObject) 
		{
			CUIRectObject* p = GetPtr(lpObject);
			if ( !p ) return false;
			return m_Value.left == p->m_Value.left && m_Value.top ==  p->m_Value.top
				&& m_Value.right == p->m_Value.right && m_Value.bottom ==  p->m_Value.bottom;
		}
		virtual	void	Copy(IUIObject* lpObject) 
		{
			CUIRectObject* p = GetPtr(lpObject);
			if ( p ) m_Value = p->m_Value;
		}
	};
	class CUIStringObject
		: public CUINoAggregateObjectImplHelper<IUIString, CUIStringObject, IUIString>
	{
		DECLARE_CLASS(CUIStringObject, string)
	public:
		CUIStringObject() { }
		CUIStringObject(wchar_t* value) { m_Value = value; }
		virtual	wchar_t*	GetValue() { return (wchar_t*)m_Value.c_str(); }
		virtual	void		SetValue(wchar_t* value) { m_Value = value; }
		virtual	bool	IsLess(IUIObject* lpObject) 
		{ 
			CUIStringObject* p = GetPtr(lpObject);
			if ( !p ) return false;
			return m_Value < p->m_Value;
		}
		virtual bool	IsEqual(IUIObject* lpObject) 
		{
			CUIStringObject* p = GetPtr(lpObject);
			if ( !p ) return false;
			return m_Value == p->m_Value;
		}
		virtual	void	Copy(IUIObject* lpObject) 
		{
			CUIStringObject* p = GetPtr(lpObject);
			if ( p ) m_Value = p->m_Value;
		}
	protected:
		std::wstring	m_Value;
	};
}
